#[deriving(PartialEq,Clone,Decodable,Encodable)]
pub struct Options {
- manifest_path: Option<String>
+ manifest_path: Option<String>,
+ update_remotes: bool
}
-hammer_config!(Options "Compile the current project")
+hammer_config!(Options "Compile the current project", |c| {
+ c.short("update_remotes", 'u')
+})
fn main() {
execute_main_without_stdin(execute);
}))
};
- ops::compile(&root, shell).map(|_| None).map_err(|err| {
+ let update = options.update_remotes;
+
+ ops::compile(&root, update, shell).map(|_| None).map_err(|err| {
CliError::from_boxed(err, 101)
})
}
let source_id = SourceId::for_git(&url, reference.as_slice());
- let mut config = try!(Config::new(shell).map_err(|e| CliError::from_boxed(e, 1)));
+ let mut config = try!(Config::new(shell, true).map_err(|e| CliError::from_boxed(e, 1)));
let mut source = GitSource::new(&source_id, &mut config);
try!(source.update().map_err(|e| {
use std::vec::Vec;
-use core::{MultiShell, Source, SourceId, Summary, Dependency, PackageId, Package};
+use core::{Source, SourceId, Summary, Dependency, PackageId, Package};
use util::{CargoResult, ChainError, Config, human};
pub trait Registry {
overrides: Vec<Summary>,
summaries: Vec<Summary>,
searched: Vec<SourceId>,
- shell: &'a mut MultiShell
+ config: &'a mut Config<'a>
}
impl<'a> PackageRegistry<'a> {
pub fn new<'a>(source_ids: Vec<SourceId>,
override_ids: Vec<SourceId>,
- shell: &'a mut MultiShell) -> CargoResult<PackageRegistry<'a>> {
+ config: &'a mut Config<'a>) -> CargoResult<PackageRegistry<'a>> {
- let mut reg = PackageRegistry::empty(shell);
+ let mut reg = PackageRegistry::empty(config);
for id in source_ids.iter() {
try!(reg.load(id, false));
Ok(reg)
}
- fn empty<'a>(shell: &'a mut MultiShell) -> PackageRegistry<'a> {
+ fn empty<'a>(config: &'a mut Config<'a>) -> PackageRegistry<'a> {
PackageRegistry {
sources: vec!(),
overrides: vec!(),
summaries: vec!(),
searched: vec!(),
- shell: shell
+ config: config
}
}
fn load(&mut self, namespace: &SourceId, override: bool) -> CargoResult<()> {
(|| {
- let mut source = namespace.load(&mut try!(Config::new(self.shell)));
+ let mut source = namespace.load(self.config);
let dst = if override {&mut self.overrides} else {&mut self.summaries};
// Ensure the source has fetched all necessary remote data.
//!
use std::os;
-use util::config::{ConfigValue};
+use util::config::{Config, ConfigValue};
use core::{MultiShell, Source, SourceId, PackageSet, resolver};
use core::registry::PackageRegistry;
use ops;
use sources::{PathSource};
use util::{CargoResult, Wrap, config, internal, human};
-pub fn compile(manifest_path: &Path, shell: &mut MultiShell) -> CargoResult<()> {
+pub fn compile(manifest_path: &Path, update: bool, shell: &mut MultiShell) -> CargoResult<()> {
log!(4, "compile; manifest-path={}", manifest_path.display());
let mut source = PathSource::for_path(&manifest_path.dir_path());
let source_ids = package.get_source_ids();
let packages = {
+ let mut config = try!(Config::new(shell, update));
+
let mut registry =
- try!(PackageRegistry::new(source_ids, override_ids, shell));
+ try!(PackageRegistry::new(source_ids, override_ids, &mut config));
let resolved =
try!(resolver::resolve(package.get_dependencies(), &mut registry));
debug!("packages={}", packages);
- try!(ops::compile_packages(&package, &PackageSet::new(packages.as_slice()), shell));
+ let mut config = try!(Config::new(shell, update));
+ try!(ops::compile_packages(&package, &PackageSet::new(packages.as_slice()), &mut config));
Ok(())
}
type Args = Vec<String>;
-struct Context<'a> {
+struct Context<'a, 'b> {
dest: &'a Path,
deps_dir: &'a Path,
primary: bool,
rustc_version: &'a str,
compiled_anything: bool,
- config: &'a mut Config<'a>
+ config: &'b mut Config<'b>
}
-pub fn compile_packages(pkg: &Package, deps: &PackageSet,
- shell: &mut MultiShell) -> CargoResult<()> {
+pub fn compile_packages<'a>(pkg: &Package, deps: &PackageSet,
+ config: &'a mut Config<'a>) -> CargoResult<()> {
+
debug!("compile_packages; pkg={}; deps={}", pkg, deps);
- let mut config = try!(Config::new(shell));
let target_dir = pkg.get_absolute_target_dir();
let deps_target_dir = target_dir.join("deps");
primary: false,
rustc_version: rustc_version.as_slice(),
compiled_anything: false,
- config: &mut config
+ config: config
};
// Traverse the dependencies in topological order
impl<'a, 'b> Source for GitSource<'a, 'b> {
fn update(&mut self) -> CargoResult<()> {
- try!(self.config.shell().status("Updating",
- format!("git repository `{}`", self.remote.get_url())));
+ let should_update = self.config.update_remotes() || {
+ !self.remote.has_ref(&self.db_path, self.reference.as_slice()).is_ok()
+ };
+
+ let repo = if should_update {
+ try!(self.config.shell().status("Updating",
+ format!("git repository `{}`", self.remote.get_url())));
+
+ log!(5, "updating git source `{}`", self.remote);
+ try!(self.remote.checkout(&self.db_path))
+ } else {
+ self.remote.db_at(&self.db_path)
+ };
- log!(5, "updating git source `{}`", self.remote);
- let repo = try!(self.remote.checkout(&self.db_path));
try!(repo.copy_to(self.reference.as_slice(), &self.checkout_path));
self.path_source.update()
)
macro_rules! git_output(
- ($config:expr, $str:expr, $($rest:expr),*) => (
+ ($config:expr, $str:expr, $($rest:expr),*) => ({
try!(git_output(&$config, format!($str, $($rest),*)))
- );
+ });
- ($config:expr, $str:expr) => (
+ ($config:expr, $str:expr) => ({
try!(git_output(&$config, format!($str)))
- );
+ });
)
macro_rules! errln(
&self.url
}
+ pub fn has_ref<S: Str>(&self, path: &Path, reference: S) -> CargoResult<()> {
+ git_output!(*path, "rev-parse {}", reference.as_slice());
+ Ok(())
+ }
+
pub fn checkout(&self, into: &Path) -> CargoResult<GitDatabase> {
if into.exists() {
try!(self.fetch_into(into));
pub struct Config<'a> {
home_path: Path,
+ update_remotes: bool,
shell: &'a mut MultiShell
}
impl<'a> Config<'a> {
- pub fn new<'a>(shell: &'a mut MultiShell) -> CargoResult<Config<'a>> {
+ pub fn new<'a>(shell: &'a mut MultiShell, update_remotes: bool) -> CargoResult<Config<'a>> {
Ok(Config {
home_path: try!(os::homedir().require(|| {
human("Cargo couldn't find your home directory. \
This probably means that $HOME was not set.")
})),
+ update_remotes: update_remotes,
shell: shell
})
}
pub fn shell<'a>(&'a mut self) -> &'a mut MultiShell {
&mut *self.shell
}
+
+ pub fn update_remotes(&mut self) -> bool {
+ self.update_remotes
+ }
}
#[deriving(Eq,PartialEq,Clone,Encodable,Decodable)]
UPDATING, git_project.root().display(),
COMPILING, git_project.root().display(),
COMPILING, p.root().display())));
+
// Don't recompile the second time
assert_that(p.process("cargo-compile"),
- execs().with_stdout(format!("{} git repository `file:{}`\n\
- {} bar v0.5.0 (file:{})\n\
+ execs().with_stdout(format!("{} bar v0.5.0 (file:{})\n\
{} foo v0.5.0 (file:{})\n",
- UPDATING, git_project.root().display(),
FRESH, git_project.root().display(),
FRESH, p.root().display())));
+
// Modify a file manually, shouldn't trigger a recompile
File::create(&git_project.root().join("src/bar.rs")).write_str(r#"
pub fn bar() { println!("hello!"); }
"#).assert();
+
assert_that(p.process("cargo-compile"),
+ execs().with_stdout(format!("{} bar v0.5.0 (file:{})\n\
+ {} foo v0.5.0 (file:{})\n",
+ FRESH, git_project.root().display(),
+ FRESH, p.root().display())));
+
+ assert_that(p.process("cargo-compile").arg("-u"),
execs().with_stdout(format!("{} git repository `file:{}`\n\
{} bar v0.5.0 (file:{})\n\
{} foo v0.5.0 (file:{})\n",
UPDATING, git_project.root().display(),
FRESH, git_project.root().display(),
FRESH, p.root().display())));
+
// Commit the changes and make sure we trigger a recompile
File::create(&git_project.root().join("src/bar.rs")).write_str(r#"
pub fn bar() { println!("hello!"); }
git_project.process("git").args(["add", "."]).exec_with_output().assert();
git_project.process("git").args(["commit", "-m", "test"]).exec_with_output()
.assert();
- assert_that(p.process("cargo-compile"),
+
+ assert_that(p.process("cargo-compile").arg("-u"),
execs().with_stdout(format!("{} git repository `file:{}`\n\
{} bar v0.5.0 (file:{})\n\
{} foo v0.5.0 (file:{})\n",